package com.hqd.ch03.v12.beans.converter.support;

import com.hqd.ch03.v12.beans.converter.ConversionService;
import com.hqd.ch03.v12.beans.converter.Converter;
import com.hqd.ch03.v12.beans.converter.ConverterRegistry;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 类型转换默认实现类
 */
public class DefaultConversionService implements ConversionService, ConverterRegistry {
    private List<Converter> converters = new ArrayList<>();

    /**
     * 获取对象的泛型
     *
     * @param src   待获取泛型对象
     * @param index 泛型的位置
     * @param <T>   泛型
     * @return 泛型Class类
     */
    public static <T> Class getInstance(Class src, int index) {
        if (src == null || index < 0) {
            return null;
        }
        Class aClass = src;
        Type gSuperclass = aClass.getGenericSuperclass();
        if (gSuperclass instanceof ParameterizedType) {
            try {
                ParameterizedType pType = (ParameterizedType) gSuperclass;
                Type[] types = pType.getActualTypeArguments();
                if (index < types.length) {
                    Class desClass = (Class<T>) types[index];
                    return desClass;
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    /**
     * 获取转换器下标
     *
     * @param sourceType
     * @param targetType
     * @return
     */
    private Converter getConverter(Class<?> sourceType, Class<?> targetType) {
        for (int i = 0; i < converters.size(); i++) {
            Class sInstance = getInstance(targetType, 0);
            Class tInstance = getInstance(targetType, 1);
            if (sourceType == sInstance && tInstance == targetType) {
                return converters.get(i);
            }
        }
        return null;
    }

    @Override
    public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
        return false;
    }

    @Override
    public <T> T convert(Object source, Class<T> targetType) {
        Class<?> sourceType = source.getClass();
        Converter converter = getConverter(sourceType, targetType);
        if (converter != null) {
            return (T) converter.convert(source);
        }
        return null;
    }

    @Override
    public void addConverter(Converter<?, ?> converter) {
        converters.add(converter);
    }

    @Override
    public void removeConvertible(Class<?> sourceType, Class<?> targetType) {
        Converter converter = getConverter(sourceType, targetType);
        if (converter != null) {
            converters.remove(converter);
        }
    }
}
